package com.tools.scanner.ui.dialog

import android.content.Context
import android.graphics.Rect
import android.os.Bundle
import android.util.Log
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.tools.scanner.R
import com.tools.scanner.bean.OcrItemInfo
import com.tools.scanner.databinding.DialogOcrTextBinding
import com.tools.scanner.databinding.RecyclerOcrTextItemBinding
import com.tools.scanner.utils.ToastUtil
import com.tools.scanner.utils.copyText
import com.tools.scanner.utils.openSearch
import com.tools.scanner.utils.shareText
import java.util.ArrayList

class OcrTextDialog(
    private val mContext: Context,
    private val mList: List<OcrItemInfo>
) : BottomSheetDialog(mContext, R.style.BottomSheetDialog) {

    private lateinit var mBinding: DialogOcrTextBinding
    private lateinit var mAdapter: OcrTextAdapter

    private var isAllSelect = false
    private var mLlCopy: LinearLayout? = null
    private var mLlSearch: LinearLayout? = null
    private var mLlShare: LinearLayout? = null

    private var mIvCopy: ImageView? = null
    private var mIvSearch: ImageView? = null
    private var mIvShare: ImageView? = null

    private var mTvCopy: TextView? = null
    private var mTvSearch: TextView? = null
    private var mTvShare: TextView? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DialogOcrTextBinding.inflate(layoutInflater)
        setContentView(mBinding.root)

        val marginTop = mContext.resources.getDimension(R.dimen.dp_8).toInt()
        mBinding.recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() {
            override fun getItemOffsets(outRect: Rect, itemPosition: Int, parent: RecyclerView) {
                if (itemPosition == 0) {
                    return
                }

                outRect.top = marginTop
            }
        })
        mBinding.recyclerView.layoutManager = LinearLayoutManager(mContext)
        mBinding.recyclerView.adapter = OcrTextAdapter(mList) {
            changeSelectState()
        }.apply {
            mAdapter = this
        }

        mBinding.ivBack.setOnClickListener {
            dismiss()
        }

        mBinding.tvSelect.setOnClickListener {
            allSelect()
        }
    }

    private fun allSelect() {
        isAllSelect = !isAllSelect
        mAdapter.changeAllSelectState(isAllSelect)
        changeSelectState()
    }

    private fun copy() {
        if (mAdapter.hasSelect()) {
            getAllSelectText().copyText()
            ToastUtil.showToast(R.string.copy_success)
        }
    }

    private fun search() {
        if (mAdapter.hasSelect()) {
            getAllSelectText().openSearch()
        }
    }

    private fun share() {
        if (mAdapter.hasSelect()) {
            getAllSelectText().shareText()
        }
    }

    private fun getAllSelectText(): String {
        val dataList = mAdapter.getAllSelectInfo()
        if (dataList.isEmpty()) {
            return ""
        } else {
            val stringBuilder = StringBuilder()

            dataList.forEach {
                stringBuilder.append(it.text).append("\r\n")
            }

            return stringBuilder.toString()
        }
    }

    override fun setContentView(view: View) {
        customEnsureContainerAndBehavior()
        super.setContentView(view)
    }

    private fun customEnsureContainerAndBehavior() {
        val ensureContainerAndBehaviorMethod =
            BottomSheetDialog::class.java.getDeclaredMethod("ensureContainerAndBehavior")
        ensureContainerAndBehaviorMethod.isAccessible = true
        ensureContainerAndBehaviorMethod.invoke(this)

        val containerField = BottomSheetDialog::class.java.getDeclaredField("container")
        containerField.isAccessible = true

        View.inflate(context, R.layout.custom_bottom_sheet_dialog, null).let { rootView ->
            containerField.set(this, rootView)

            val coordinator = rootView.findViewById<CoordinatorLayout>(R.id.coordinator)
            val coordinatorField = BottomSheetDialog::class.java.getDeclaredField("coordinator")
            coordinatorField.isAccessible = true
            coordinatorField.set(this, coordinator)

            val bottomSheetField = BottomSheetDialog::class.java.getDeclaredField("bottomSheet")
            bottomSheetField.isAccessible = true
            bottomSheetField.set(this, rootView.findViewById(R.id.design_bottom_sheet))
            val bottomSheet = bottomSheetField.get(this) as FrameLayout

            val behaviorField = BottomSheetDialog::class.java.getDeclaredField("behavior")
            behaviorField.isAccessible = true
            val oldBehavior = behaviorField.get(this) as BottomSheetBehavior<*>

            val callbacksField = BottomSheetBehavior::class.java.getDeclaredField("callbacks")
            callbacksField.isAccessible = true
            val callbacks =
                callbacksField.get(oldBehavior) as ArrayList<BottomSheetBehavior.BottomSheetCallback>

            val behavior = BottomSheetBehavior.from(bottomSheet)
            behavior.isHideable = true
            behaviorField.set(this, behavior)
            callbacks.forEach {
                behavior.addBottomSheetCallback(it)
            }

            val llTools = rootView.findViewById<LinearLayout>(R.id.ll_tools)
            llTools.post {
                val height = llTools.measuredHeight
                val layoutParams = coordinator.layoutParams as FrameLayout.LayoutParams
                layoutParams.setMargins(0, 0, 0, height)
                coordinator.layoutParams = layoutParams
            }

            mLlCopy = rootView.findViewById(R.id.ll_copy)
            mLlSearch = rootView.findViewById(R.id.ll_search)
            mLlShare = rootView.findViewById(R.id.ll_share)

            mIvCopy = rootView.findViewById(R.id.iv_copy)
            mIvSearch = rootView.findViewById(R.id.iv_search)
            mIvShare = rootView.findViewById(R.id.iv_share)

            mTvCopy = rootView.findViewById(R.id.tv_copy)
            mTvSearch = rootView.findViewById(R.id.tv_search)
            mTvShare = rootView.findViewById(R.id.tv_share)

            mLlCopy?.setOnClickListener {
                copy()
            }
            mLlSearch?.setOnClickListener {
                search()
            }
            mLlShare?.setOnClickListener {
                share()
            }
        }
    }

    private fun changeSelectState() {
        isAllSelect = mAdapter.isAllSelect()
        if (mAdapter.isAllSelect()) {
            mBinding.tvSelect.setText(R.string.all_no_select)
        } else {
            mBinding.tvSelect.setText(R.string.all_select)
        }

        if (mAdapter.hasSelect()) {
            mIvCopy?.setImageResource(R.drawable.ic_copy_black)
            mIvSearch?.setImageResource(R.drawable.ic_search_black)
            mIvShare?.setImageResource(R.drawable.ic_share_black)

            val color = mContext.resources.getColor(R.color.color_000000)
            mTvCopy?.setTextColor(color)
            mTvSearch?.setTextColor(color)
            mTvShare?.setTextColor(color)
        } else {
            mIvCopy?.setImageResource(R.drawable.ic_copy_bf)
            mIvSearch?.setImageResource(R.drawable.ic_search_bf)
            mIvShare?.setImageResource(R.drawable.ic_share_bf)

            val color = mContext.resources.getColor(R.color.color_bfbfbf)
            mTvCopy?.setTextColor(color)
            mTvSearch?.setTextColor(color)
            mTvShare?.setTextColor(color)
        }
    }

    override fun show() {
        super.show()
        window?.let {
            it.setGravity(Gravity.BOTTOM)
            val layoutParams = it.attributes
            layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT
            layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT
            it.attributes = layoutParams
        }
    }
}

data class OcrTextItemInfo(val text: String, var isSelect: Boolean = false)

class OcrTextAdapter(
    private val dataList: List<OcrItemInfo>,
    private val mSelectCallback: (itemInfo: OcrTextItemInfo) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private val mList = mutableListOf<OcrTextItemInfo>()
    private var mSelectCount = 0

    init {
        dataList.forEach {
            val text = if (it.isTranslate) {
                it.translateText ?: ""
            } else {
                it.originalText
            }

            mList.add(OcrTextItemInfo(text))
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding = RecyclerOcrTextItemBinding.inflate(layoutInflater, parent, false)
        return OcrTextViewHolder(binding) { position ->
            val item = mList[position]
            item.isSelect = !item.isSelect
            if (item.isSelect) {
                mSelectCount++
            } else {
                mSelectCount--
            }
            notifyItemChanged(position)
            mSelectCallback(item)
        }
    }

    override fun getItemCount(): Int {
        return mList.size
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if (holder is OcrTextViewHolder) {
            holder.refresh(mList[position])
        }
    }

    fun changeAllSelectState(isAllSelect: Boolean) {
        mList.forEach {
            it.isSelect = isAllSelect
        }
        mSelectCount = if (isAllSelect) {
            mList.size
        } else {
            0
        }
        notifyDataSetChanged()
    }

    fun getAllSelectInfo(): List<OcrTextItemInfo> {
        val result = mutableListOf<OcrTextItemInfo>()
        mList.forEach {
            if (it.isSelect) {
                result.add(it)
            }
        }
        return result
    }

    fun hasSelect(): Boolean {
        return mSelectCount > 0
    }

    fun isAllSelect(): Boolean {
        return mSelectCount == mList.size
    }

    private class OcrTextViewHolder(
        private val mBinding: RecyclerOcrTextItemBinding,
        private val mCallback: (position: Int) -> Unit
    ) : RecyclerView.ViewHolder(mBinding.root) {

        init {
            mBinding.textView.setOnClickListener {
                mCallback(adapterPosition)
            }
        }

        fun refresh(ocrInfo: OcrTextItemInfo) {
            mBinding.textView.text = ocrInfo.text
            if (ocrInfo.isSelect) {
                mBinding.textView.setBackgroundResource(R.color.color_e1f5fe)
            } else {
                mBinding.textView.setBackgroundResource(R.color.color_F5F5F5)
            }
        }

    }

}